package modelo;

import java.io.File;
import java.util.List;

import org.dom4j.DocumentException;

import modelo.arma.Cuchillo;
import modelo.arma.Pistola;
import modelo.configuraciones.ConfiguracionCiudadesYObjetos;
import modelo.configuraciones.ConfiguracionCiudadesYObjetosPorDefecto;
import modelo.configuraciones.ConfiguracionCiudadesYObjetosXML;
import modelo.configuraciones.ConfiguracionLadrones;
import modelo.configuraciones.ConfiguracionLadronesPorDefecto;
import modelo.configuraciones.ConfiguracionLadronesXML;
import modelo.geografia.Ciudad;
import modelo.geografia.SistemaDeViajes;
import modelo.ladron.EstrategiaDeEscape;
import modelo.ladron.Ladron;
import modelo.ladron.OrdenDeArresto;
import modelo.objeto.ObjetoRobado;
import modelo.policia.Policia;
import modelo.tiempo.Tiempo;
import modelo.tiempo.TurnoLadron;


public class Juego{
	
	private Ladron ladron;
	private ObjetoRobado objetoRobado;
	private Policia policiaJugando;
	private List<Ladron> ladrones;
	private List<Ciudad> ciudades;
	private ConfiguracionCiudadesYObjetos configCiudadesYObjetos;
	private ConfiguracionLadrones configLadrones;
	private Ciudad proximaCiudadCorrectaParaQueVayaElPolicia; //para jugar a traves de tests.
	private SistemaDeViajes viajes;
	private boolean casoFinalizado;
	
	public Juego(Policia policia) { 
		policiaJugando = policia;
		policia.asignarCaso(this);
		ladron = null;
		objetoRobado = null;
		viajes = new SistemaDeViajes();
		this.setearPaisesAMostrar();
		this.configurarJuego();
	}
	private void configurarJuego() {
		File archivoLadrones = new File("Ladrones.xml");
		File archivoCiudades = new File("CiudadesYObjetos.xml");
		try {
			if (archivoCiudades.exists()) configCiudadesYObjetos = new ConfiguracionCiudadesYObjetosXML(archivoCiudades);
				else configCiudadesYObjetos = new ConfiguracionCiudadesYObjetosPorDefecto(); 
		} catch (DocumentException e) {
			configCiudadesYObjetos = new ConfiguracionCiudadesYObjetosPorDefecto();
		}
		try {
			if (archivoLadrones.exists()) configLadrones = new ConfiguracionLadronesXML(archivoLadrones);
				else configLadrones = new ConfiguracionLadronesPorDefecto();
		} catch (DocumentException e){
			configLadrones = new ConfiguracionLadronesPorDefecto();
		}
		ciudades = configCiudadesYObjetos.obtenerCiudades();
		ladrones = configLadrones.obtenerLadrones();
	}
	public void comenzarJuego() {
		if (casoFinalizado){
			Tiempo.borrarInstancia();
			policiaJugando.asignarCaso(this);
			policiaJugando.reiniciarPolicia();
			viajes = new SistemaDeViajes();
			this.setearPaisesAMostrar();
			this.configurarJuego();	
		}
		TurnoLadron turno = null;
		turno = new TurnoLadron(this);
		Tiempo tiempo = Tiempo.obtenerInstancia();
		tiempo.setearTurnoDelLadron(turno);
		objetoRobado = (configCiudadesYObjetos.obtenerObjetoARobar(policiaJugando.grado()));
		ladron = configLadrones.seleccionarLadron();	
		ladron.robarObjeto(objetoRobado);
		EstrategiaDeEscape estrategia = new EstrategiaDeEscape(ciudades, objetoRobado);		
		ladron.setearEstrategiaDeEscape(estrategia);
		policiaJugando.irACiudadDondeSeRobo(objetoRobado.getCiudadALaQuePertenece());
		turno.setHorasPorTurno(policiaJugando.grado());
		casoFinalizado = false;
	}	
	public void setearPaisesAMostrar(){
		viajes.setearCantidadDeCiudadesAMostrar(policiaJugando.grado());
	}
	public Ladron getLadron(){
		return ladron;
	}
	public void terminaElTurnoDelLadron(){
		ladron.escapar();
	}
	public void determinarSiSucedeAtaqueCasual() {
		int probabilidad = ((int)(Math.random()*100));
		if (probabilidad>90 && probabilidad<95) {
			Cuchillo.obtenerInstancia().herirPolicia();
		}
		if (probabilidad>95) {
			Pistola.obtenerInstancia().herirPolicia();
		}
	}
	public ObjetoRobado getObjetoRobado() {
		return objetoRobado;
	}
	public List<Ciudad> getCiudades(){
		return ciudades;		
	}
	public List<Ladron> getTodosLosLadrones(){
		return ladrones;
	}
	public Policia getPolicia(){
		return policiaJugando;
	}
	public Ciudad getProximaCiudadCorrectaParaQueVayaElPolicia(){
		return proximaCiudadCorrectaParaQueVayaElPolicia;
	}
	public List<Ciudad> ofrecerCiudadesAlPolicia(){
		List<Ciudad> ciudadesAOfrecer = viajes.ofrecerCiudadesAlPolicia(policiaJugando, ladron, ciudades);
		proximaCiudadCorrectaParaQueVayaElPolicia = viajes.getProximaCiudadCorrectaParaQueVayaElPolicia();
		return ciudadesAOfrecer;
	}
	public boolean estanEnLaMismaCiudad(){
		if (policiaJugando.getCiudadActual() == ladron.ciudadActual()) return true;
		else return false;
	}
	public boolean verificarOrdenDeArresto(){
		OrdenDeArresto ordenDeArresto = OrdenDeArresto.obtenerInstancia();
		if(ordenDeArresto.getNombreLadron() == ladron.getNombre()) return true;
		else return false;
	}
	public int calcularDistanciaEntreCiudades(Ciudad origen, Ciudad destino){
		return viajes.calcularDistanciaEnKmEntre2Ciudades(origen, destino);
	}
	public boolean casoFinalizado(){
		return casoFinalizado;
	}
	public void winGame(){
		policiaJugando.casoResuelto();
		casoFinalizado = true;
	}
	public void gameOver(){
		casoFinalizado = true;
	}
}
